package com.zhengbing.tj.design.async;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * 异步执行控制器
 * 提供RESTful接口演示异步执行的各种场景
 * 
 * @author zhengbing
 * @since 2024-08-21
 */
@RestController
@RequestMapping("/design/async")
public class AsyncController {

    private static final Logger logger = LoggerFactory.getLogger(AsyncController.class);

    @Autowired
    private AsyncService asyncService;

    /**
     * 简单异步任务接口
     * 演示基本的异步执行
     *
     * @param message 测试消息
     * @return 立即返回的响应
     */
    @GetMapping("/simple")
    public String simpleAsync(@RequestParam(defaultValue = "Hello Async") String message) {
        logger.info("接收到简单异步任务请求: {}", message);
        asyncService.simpleAsyncTask(message);
        return "异步任务已提交，正在后台执行中...";
    }

    /**
     * 带返回值的异步任务接口
     * 演示如何获取异步计算结果
     *
     * @param number 计算数字
     * @return 计算结果
     */
    @GetMapping("/calculate")
    public String calculateAsync(@RequestParam int number) {
        logger.info("接收到计算请求: {}", number);
        
        CompletableFuture<Integer> future = asyncService.calculateAsync(number);
        
        try {
            // 等待异步结果（实际项目中应该异步获取）
            int result = future.get();
            return "计算完成: " + number + "² = " + result;
        } catch (InterruptedException | ExecutionException e) {
            logger.error("计算任务失败", e);
            return "计算任务失败: " + e.getMessage();
        }
    }

    /**
     * 邮件发送异步任务接口
     * 演示使用自定义线程池的异步执行
     *
     * @param email 邮件地址
     * @param content 邮件内容
     * @return 立即返回的响应
     */
    @PostMapping("/email")
    public String sendEmailAsync(@RequestParam String email, @RequestParam String content) {
        logger.info("接收到邮件发送请求: {} -> {}", email, content);
        asyncService.sendEmailAsync(email, content);
        return "邮件发送任务已提交，正在后台发送中...";
    }

    /**
     * 批量异步任务接口
     * 演示同时处理多个异步任务
     *
     * @param items 处理项目列表，逗号分隔
     * @return 立即返回的响应
     */
    @PostMapping("/batch")
    public String processBatch(@RequestParam String items) {
        String[] itemArray = items.split(",");
        logger.info("接收到批量处理请求: {}", Arrays.toString(itemArray));
        asyncService.processBatchAsync(itemArray);
        return "批量任务已提交，正在后台处理中...";
    }

    /**
     * 异常处理异步任务接口
     * 演示异步任务中的异常处理
     *
     * @param shouldFail 是否故意失败
     * @return 执行结果
     */
    @GetMapping("/risky")
    public String riskyTask(@RequestParam(defaultValue = "false") boolean shouldFail) {
        logger.info("接收到风险任务请求: shouldFail={}", shouldFail);
        
        CompletableFuture<String> future = asyncService.riskyAsyncTask(shouldFail);
        
        try {
            String result = future.get();
            return "任务执行成功: " + result;
        } catch (InterruptedException | ExecutionException e) {
            logger.error("任务执行失败", e);
            return "任务执行失败: " + e.getCause().getMessage();
        }
    }

    /**
     * 组合异步任务接口
     * 演示多个异步任务的组合执行
     *
     * @param numbers 计算数字列表，逗号分隔
     * @return 所有计算结果
     */
    @GetMapping("/combined")
    public String combinedTasks(@RequestParam String numbers) {
        String[] numArray = numbers.split(",");
        logger.info("接收到组合计算请求: {}", Arrays.toString(numArray));
        
        CompletableFuture<Integer>[] futures = new CompletableFuture[numArray.length];
        
        for (int i = 0; i < numArray.length; i++) {
            int num = Integer.parseInt(numArray[i].trim());
            futures[i] = asyncService.calculateAsync(num);
        }
        
        try {
            CompletableFuture.allOf(futures).join();
            
            StringBuilder result = new StringBuilder("所有计算完成:\n");
            for (int i = 0; i < numArray.length; i++) {
                int num = Integer.parseInt(numArray[i].trim());
                int square = futures[i].get();
                result.append(num).append("² = ").append(square).append("\n");
            }
            
            return result.toString();
        } catch (InterruptedException | ExecutionException e) {
            logger.error("组合任务失败", e);
            return "组合任务执行失败: " + e.getMessage();
        }
    }
}